import axios, { AxiosInstance, isCancel } from 'axios';
import { QsRequestInterceptors, QsRequestConfig } from './type.ts';
import type { Result, QsInternalAxiosRequestConfig } from './type';

class BaseRequest {
    readonly instance: AxiosInstance;
    readonly interceptors: QsRequestInterceptors;
    readonly isCancel: any;
    constructor(config: QsRequestConfig) {
        this.instance = axios.create(config);
        this.isCancel = isCancel;
        this.interceptors = config.interceptors;

        // 在创建的axios上使用request拦截器
        this.instance.interceptors.request.use(
            this.interceptors.requestInterceptor,
            this.interceptors.requestInterceptorCatch
        );

        // 在创建的axios上使用response拦截器
        this.instance.interceptors.response.use(
            this.interceptors.responseInterceptor,
            this.interceptors.responseInterceptorCatch
        );
    }
}

class QAxios extends BaseRequest {
    constructor(config: QsRequestConfig) {
        super(config);
    }
    request<T = any, R = Result<T>, D = any>(config: QsInternalAxiosRequestConfig<D>): Promise<R> {
        return new Promise(async (resolve, reject) => {
            try {
                const res = await this.instance.request<R>(config);
                resolve(res.data);
            } catch (e) {
                reject(e);
            }
        });
    }
    get<T = any, R = Result<T>, D = any>(
        url: string,
        config?: QsInternalAxiosRequestConfig<D>
    ): Promise<R> {
        return new Promise(async (resolve, reject) => {
            try {
                const res = await this.instance.get<R>(url, config);
                resolve(res?.data);
            } catch (e) {
                reject(e);
            }
        });
    }
    delete<T = any, R = Result<T>, D = any>(
        url: string,
        config?: QsInternalAxiosRequestConfig<D>
    ): Promise<R> {
        return new Promise(async (resolve, reject) => {
            try {
                const res = await this.instance.delete<R>(url, config);
                resolve(res.data);
            } catch (e) {
                reject(e);
            }
        });
    }
    options<T = any, R = Result<T>, D = any>(
        url: string,
        config?: QsInternalAxiosRequestConfig<D>
    ): Promise<R> {
        return new Promise(async (resolve, reject) => {
            try {
                const res = await this.instance.options<R>(url, config);
                resolve(res.data);
            } catch (e) {
                reject(e);
            }
        });
    }
    post<T = any, R = Result<T>, D = any>(
        url: string,
        data?: D,
        config?: QsInternalAxiosRequestConfig<D>
    ): Promise<R> {
        return new Promise(async (resolve, reject) => {
            try {
                const res = await this.instance.post<R>(url, data, config);
                resolve(res.data);
            } catch (e) {
                reject(e);
            }
        });
    }
    put<T = any, R = Result<T>, D = any>(
        url: string,
        data?: D,
        config?: QsInternalAxiosRequestConfig<D>
    ): Promise<R> {
        return new Promise(async (resolve, reject) => {
            try {
                const res = await this.instance.put<R>(url, data, config);
                resolve(res.data);
            } catch (e) {
                reject(e);
            }
        });
    }
    patch<T = any, R = Result<T>, D = any>(
        url: string,
        data?: D,
        config?: QsInternalAxiosRequestConfig<D>
    ): Promise<R> {
        return new Promise(async (resolve, reject) => {
            try {
                const res = await this.instance.patch<R>(url, data, config);
                resolve(res.data);
            } catch (e) {
                reject(e);
            }
        });
    }
}

export default QAxios;
